// SPDX-License-Identifier: GPL-2.0+

#include <common.h>
#include <asm/sections.h>
#include <asm/global_data.h>

#include <asm/io.h>

DECLARE_GLOBAL_DATA_PTR;

#ifdef CONFIG_SPL_BOARD_INIT
__weak void spl_board_init(void)
{
	return ;
}
#endif

#ifdef CONFIG_LOONGARCH
static u32 get_fdt_totalsize(const void *fdt)
{
	int conf, node, fdt_node, images, len;
	const char *fdt_name;
	const u32 *fdt_len;
	u32 totalsize = 0;

	if (fdt_check_header(fdt))
		return 0;

	totalsize = fdt_totalsize(fdt);

	conf = fdt_path_offset(fdt, FIT_CONFS_PATH);
	if (conf < 0) {
		debug("%s: Cannot find /configurations node: %d\n", __func__,
			  conf);
		goto finish;
	}

	images = fdt_path_offset(fdt, FIT_IMAGES_PATH);
	if (images < 0) {
		debug("%s: Cannot find /images node: %d\n", __func__, images);
		goto finish;
	}

	for (node = fdt_first_subnode(fdt, conf);
		node >= 0;
		node = fdt_next_subnode(fdt, node)) {

		fdt_name = fdt_getprop(fdt, node, FIT_FDT_PROP, &len);
		if (!fdt_name)
			continue;

		fdt_node = fdt_subnode_offset(fdt, images, fdt_name);
		if (fdt_node < 0)
			continue;

		fdt_len = fdt_getprop(fdt, fdt_node, "data-size", &len);
		if (!fdt_len || len != sizeof(*fdt_len))
			continue;

		totalsize += ALIGN(fdt32_to_cpu(*fdt_len), 4);
	}

finish:
	debug("fdt total size: %d\n", totalsize);
	return totalsize;
}

void *board_fdt_blob_setup(void)
{
#ifdef CONFIG_SPL
	uint8_t *fdt_dst;
	uint8_t *fdt_src;
	ulong size;

	fdt_dst = (uint8_t*)ALIGN((ulong)&__bss_end, ARCH_DMA_MINALIGN);
#ifdef CONFIG_SPL_BUILD
	fdt_src = (uint8_t*)((ulong)&_image_binary_end - (ulong)__text_start +
                        PHYS_TO_UNCACHED(BOOT_SPACE_BASE));
#else
	fdt_src = (uint8_t*)&_image_binary_end;

	//当fdt段落在bss段里面时，需要把fdt复制到bss外面，因为启动过程中bss段会被清零，
	//当fdt段落在bss段外面时，返回fdt段的地址即可。
	if ((ulong)fdt_src >= (ulong)&__bss_end)
		fdt_dst = fdt_src;
#endif

	if (fdt_dst != fdt_src) {
		size = get_fdt_totalsize(fdt_src);
		memmove(fdt_dst, fdt_src, size);
		gd->fdt_size = size;
	}

	return fdt_dst;
#else
	return (void*)gd->fdt_blob;
#endif
}
#endif //CONFIG_LOONGARCH

#ifdef CONFIG_MIPS
#ifdef CONFIG_SPL_BUILD
//不使用SPL_BUILD时board_fdt_blob_setup函数使用uboot默认的
void *board_fdt_blob_setup(void)
{
#if 0
	uint8_t *fdt_dst;
	uint8_t *fdt_src;
	ulong size;

	fdt_dst = (uint8_t*)ALIGN((ulong)&__bss_end, ARCH_DMA_MINALIGN);
	fdt_src = (uint8_t*)((ulong)&__image_copy_end - (ulong)_start +
                        BOOT_SPACE_BASE);

	if (fdt_dst != fdt_src) {
		size = get_fdt_totalsize(fdt_src);
		memmove(fdt_dst, fdt_src, size);
		gd->fdt_size = size;
	}

	return fdt_dst;
#else
	void *fdt_blob = NULL;
	fdt_blob = (ulong *)&__image_copy_end;
	return fdt_blob;
#endif
}
#endif
#endif //CONFIG_MIPS